package com.lion.seaman.server.drivers;


import com.lion.seaman.common.Constants;
import com.lion.seaman.common.tools.StringTools;
import com.lion.seaman.orm.bin.SpringContext;
import org.apache.log4j.Logger;
import org.quartz.*;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 调度控制
 * Created by liyongyao on 17-7-18.
 */
public class JobDriverManager {
    public Logger log = Logger.getLogger(JobDriverManager.class);
    public static JobDriverManager JOB = new JobDriverManager();
    Scheduler scheduler = SpringContext.getBean(SchedulerFactoryBean.class).getScheduler();

    private JobDriverManager() {
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void list() {
        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(null);
            for (JobKey jobKey : jobKeys) {
                System.out.println(jobKey.getName());
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void saveOrUpdate(JobDriver jobDriver) throws SchedulerException {
        saveOrUpdate(jobDriver.getName(), JobDriver.class, jobDriver.getGroup(), jobDriver.getCron(), jobDriver.getDescription(), jobDriver.getData());
    }

    /**
     * 增加调度任务
     *
     * @param name  任务名称
     * @param clazz 任务类
     * @param group 任务组
     * @param cron  调度时间表达式
     * @throws SchedulerException
     */
    public void add(String name, Class<? extends Job> clazz, String group, String cron, String description, Map<String, Object> jobDataMap) throws SchedulerException {
        if (StringTools.isBlank(group)) {
            group = Constants.DEFAULT_JOB_GROUP;
        }
        JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(name, group).withDescription(description).build();
        jobDetail.getJobDataMap().putAll(jobDataMap);
        scheduler.scheduleJob(jobDetail,
                TriggerBuilder.newTrigger().withIdentity(name, group).withSchedule(CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing()).build()
        );
    }

    /**
     * 更新调度任务
     *
     * @param name  任务名称
     * @param group 任务组
     * @param cron  调度时间表达式
     * @throws SchedulerException
     */
    public void update(String name, Class<? extends Job> clazz, String group, String cron, String description, Map<String, Object> jobDataMap) throws SchedulerException {
        if (StringTools.isBlank(group)) {
            group = Constants.DEFAULT_JOB_GROUP;
        }
        JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(name, group).withDescription(description).build();
        jobDetail.getJobDataMap().putAll(jobDataMap);
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group).withSchedule(CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing()).build();
        Set<CronTrigger> triggers = new HashSet<>();
        triggers.add(trigger);
        scheduler.scheduleJob(jobDetail, triggers, true);
    }

    public void saveOrUpdate(String name, Class<? extends Job> clazz, String group, String cron, String description, Map<String, Object> jobDataMap) throws SchedulerException {

        if (scheduler.checkExists(JobKey.jobKey(name, group))) {
            update(name, clazz, group, cron, description, jobDataMap);
        } else {
            add(name, clazz, group, cron, description, jobDataMap);
        }
    }

    public boolean exists(String name, String group) {
        try {
            if (StringTools.isBlank(group)) {
                group = Constants.DEFAULT_JOB_GROUP;
            }
            return scheduler.checkExists(JobKey.jobKey(name, group));
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("exists method has error:", e);
            return false;
        }
    }

    /**
     * 暂停调度任务
     *
     * @param name  任务名称
     * @param group 任务组
     * @throws SchedulerException
     */
    public boolean pause(String name, String group) {
        try {
            if (StringTools.isBlank(group)) {
                group = Constants.DEFAULT_JOB_GROUP;
            }
            scheduler.pauseJob(JobKey.jobKey(name, group));
            return true;
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("pause method has error:", e);
            return false;
        }
    }

    /**
     * 重置调度任务
     *
     * @param name  任务名称
     * @param group 任务组
     * @throws SchedulerException
     */
    public boolean resume(String name, String group) {
        try {
            if (StringTools.isBlank(group)) {
                group = Constants.DEFAULT_JOB_GROUP;
            }
            scheduler.resumeJob(JobKey.jobKey(name, group));
            return true;
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("resume method has error:", e);
            return false;
        }
    }

    /**
     * 删除调度任务
     *
     * @param name  任务名称
     * @param group 任务组
     * @throws SchedulerException
     */
    public boolean delete(String name, String group) {
        try {
            if (StringTools.isBlank(group)) {
                group = Constants.DEFAULT_JOB_GROUP;
            }
            scheduler.deleteJob(JobKey.jobKey(name, group));
            return true;
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("delete method has error:", e);
            return false;
        }
    }

    /**
     * 任务状态
     *
     * @param name
     * @param group
     * @return
     */
    public Trigger.TriggerState state(String name, String group) {
        try {
            if (StringTools.isBlank(group)) {
                group = Constants.DEFAULT_JOB_GROUP;
            }
            Trigger.TriggerState state = scheduler.getTriggerState(TriggerKey.triggerKey(name, group));
            return state;
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("state method has error:", e);
        }
        return Trigger.TriggerState.ERROR;
    }

}
